// Copyright 2022 Huawei Cloud Computing Technology Co., Ltd.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "CaeMediaConfig.h"
#include "cJSON.h"
#include <utility>
#include <vector>
#include "../cae_common/CaeLogConfig.h"
#include "../cae_common/CaeCommon.h"
#include "../cae_common/CaeAppCtrlCmdUtils.h"

namespace {
const char *AV_VIDEO_FRAME_TYPE = "frame_type";
const char *AV_FPS = "fps";
const char *AV_BITRATE = "bitrate";
const char *AV_GOP_SIZE = "gop";
const char *AV_PROFILE_TYPE = "profile";
const char *AV_RC_MODE = "rcmode";

const char *AV_STREAM_WIDTH = "stream_width";
const char *AV_STREAM_HEIGHT = "stream_height";
const char *AV_PHYSICAL_HEIGHT = "height";
const char *AV_PHYSICAL_WIDTH = "width";

const char *VIDEO_FRAME_TYPE_H264 = "h264";
const char *VIDEO_FRAME_TYPE_H265 = "h265";
const char *VIDEO_FRAME_TYPE_YUV = "yuv";
const char *VIDEO_FRAME_TYPE_RGB = "rgb";

const char *AV_MUTE = "mute";
const char *AV_AUDIO_TYPE = "audioType";
const char *AV_SAMPLE_RATE = "sampleRate";
const char *AV_CHANNELS = "channels";
const char *AV_INTERVAL = "interval";

const int PROFILE_TYPE_BASELINE = 66;
const int PROFILE_TYPE_MAIN = 77;
const int PROFILE_TYPE_HIGH = 100;

const int RC_MODE_TYPE_ABR = 0;
const int RC_MODE_TYPE_CRF = 1;
const int RC_MODE_TYPE_CBR = 2;

const int ENCODE_TYPE_DEFAULT = 0;
const int GOP_SIZE_DEFAULT_VALUE = 240;
const int BITRATE_DEFAULT_VALUE = 3000000;
const int AUDIO_TYPE_OPUS = 0;
const int AUDIO_TYPE_PCM = 1;

const char *QUALITY_BEST = "best";
const char *QUALITY_MAIN = "main";
const char *QUALITY_BASIC = "basic";
const int SPEC_1080P_WIDTH = 1080;

const int QUALITY[4] = {625000, 930000, 2000000, 2500000};
}

CaeMediaConfig &CaeMediaConfig::GetInstance()
{
    static CaeMediaConfig instance;
    return instance;
}

CaeMediaConfig::CaeMediaConfig()
{
    InitMediaConfig();
}

void CaeMediaConfig::InitMediaConfig()
{
    m_fps = CaeConfigManage::GetFps();
    m_gopSize = 3000;
    m_bitrate = 3000000;
    m_cmdBitrate = 3000000;
    m_profile = PROFILE_TYPE_MAIN;
    m_rcMode = RC_MODE_TYPE_CBR;
    m_physicalWidth = CaeConfigManage::GetHardwareWidth();
    m_physicalHeight = CaeConfigManage::GetHardwareHeight();
    m_virtualWidthAlign = m_physicalWidth % 8 == 0 ? m_physicalWidth : (m_physicalWidth / 8 + 1) * 8;
    m_virtualHeightAlign = m_physicalHeight % 8 == 0 ? m_physicalHeight : (m_physicalHeight / 8 + 1) * 8;
    // 虚拟分辨率与8对齐
    m_streamWidth = m_virtualWidthAlign;
    m_streamHeight = m_virtualHeightAlign;
    m_remoteSchedulingElbIp = CaeConfigManage::GetPoolSchedulingElbIp();
    m_remoteSchedulingElbPort = CaeConfigManage::GetPoolSchedulingElbPort();
    m_encodeType = ENCODE_TYPE_DEFAULT;
    m_videoFrameType = !m_remoteSchedulingElbIp.empty() && m_remoteSchedulingElbPort != 0 ? VIDEO_FRAME_TYPE_H265 : VIDEO_FRAME_TYPE_H264;
    m_repeatFps = 30;


    m_autoQuality = true;
    m_isMute = false;
    m_audioType = AUDIO_TYPE_OPUS;
    m_sampleRate = 48000;
    m_channels = 2;
    m_opusInterval = 10;
    m_opusBitrate = 2 * m_channels * m_sampleRate;
    m_profile = PROFILE_TYPE_MAIN;
    m_rcMode = RC_MODE_TYPE_CBR;

    if (m_physicalWidth <= 720) {
        m_bitrate = m_fps <= 30 ? 2500000 : 3000000;
        m_cmdBitrate = m_bitrate;
    } else {
        m_bitrate = m_fps <= 30 ? 3000000 : 5000000;
        m_cmdBitrate = m_bitrate;
    }
}

CaeMediaConfig::~CaeMediaConfig() {}

void CaeMediaConfig::ClearMediaConfig()
{
    InitMediaConfig();
}

void CaeMediaConfig::SetVideoFrameType(const char* videoFrameType)
{
    m_videoFrameType = std::move(videoFrameType);
}

std::string CaeMediaConfig::GetVideoFrameType()
{
    return m_videoFrameType;
}

void CaeMediaConfig::SetFrameRate(const char* frameRate)
{
    m_fps = CaeCommon::StrToUInt32(AV_FPS,
                                   frameRate,
                                   m_fps);;
}

uint32_t CaeMediaConfig::GetFrameRate()
{
    return m_fps;
}

void CaeMediaConfig::SetBitrate(const char* bitrate, bool cmdSet)
{
    m_bitrate = CaeCommon::StrToUInt32(KEY_BITRATE.c_str(),
                                       bitrate,
                                       BITRATE_DEFAULT_VALUE);
    if (cmdSet) {
        m_cmdBitrate = m_bitrate;
    }
}

uint32_t CaeMediaConfig::GetBitrate()
{
    return m_bitrate;
}

uint32_t CaeMediaConfig::GetCmdBitrate()
{
    return m_cmdBitrate;
}


void CaeMediaConfig::SetGopSize(const char* gopSize)
{
    m_gopSize = CaeCommon::StrToUInt32(AV_GOP_SIZE,
                                       gopSize,
                                       GOP_SIZE_DEFAULT_VALUE);;
}

uint32_t CaeMediaConfig::GetGopSize()
{
    return m_gopSize;
}

void CaeMediaConfig::SetProfile(const char* profile)
{
    m_profile = CaeCommon::StrToUInt32(AV_PROFILE_TYPE,
                                       profile,
                                       PROFILE_TYPE_MAIN);
}

uint32_t CaeMediaConfig::GetProfile()
{
    return m_profile;
}

void CaeMediaConfig::SetRcMode(const char* rcMode)
{
    m_rcMode = CaeCommon::StrToUInt32(AV_RC_MODE,
                                      rcMode,
                                      RC_MODE_TYPE_CBR);
}

uint32_t CaeMediaConfig::GetRcMode()
{
    return m_rcMode;
}

void CaeMediaConfig::SetPhysicalWidth(uint32_t physicalWidth)
{
    m_physicalWidth = physicalWidth - physicalWidth % 8;
    m_streamWidth = m_physicalWidth;
    m_virtualWidthAlign = m_physicalWidth;
}

uint32_t CaeMediaConfig::GetPhysicalWidth()
{
    return m_physicalWidth;
}

void CaeMediaConfig::SetPhysicalHeight(uint32_t physicalHeight)
{
    m_physicalHeight = physicalHeight - physicalHeight % 8;
    m_streamHeight = m_physicalHeight;
    m_virtualHeightAlign = m_physicalHeight;
}

uint32_t CaeMediaConfig::GetPhysicalHeight()
{
    return m_physicalHeight;
}

void CaeMediaConfig::SetStreamWidth(const char* streamWidth)
{
    m_streamWidth = CaeCommon::StrToUInt32(KEY_STREAM_WIDTH.c_str(),
                                           streamWidth,
                                           m_streamWidth);
}

uint32_t CaeMediaConfig::GetStreamWidth()
{
    return m_streamWidth;
}

void CaeMediaConfig::SetStreamHeight(const char* streamHeight)
{
    m_streamHeight = CaeCommon::StrToUInt32(KEY_STREAM_WIDTH.c_str(),
                                            streamHeight,
                                            m_streamWidth);
}

uint32_t CaeMediaConfig::GetStreamHeight()
{
    return m_streamHeight;
}

uint32_t CaeMediaConfig::GetEncodeType()
{
    return m_encodeType;
}

void CaeMediaConfig::SetEncodeType(const char* encodeType)
{
    m_encodeType = CaeCommon::StrToUInt32(KEY_ENCODE_TYPE.c_str(),
                                          encodeType,
                                          ENCODE_TYPE_DEFAULT);
}

void CaeMediaConfig::SetRemoteSchedulingElbIp(const char* remoteSchedulingElbIp) {
    m_remoteSchedulingElbIp = std::move(remoteSchedulingElbIp);
}
std::string CaeMediaConfig::GetRemoteSchedulingElbIp()
{
    return m_remoteSchedulingElbIp;
}

uint32_t CaeMediaConfig::GetRemoteSchedulingElbPort()
{
    return m_remoteSchedulingElbPort;
}

void CaeMediaConfig::SetRemoteSchedulingElbPort(const char* remoteSchedulingElbPort)
{
    m_remoteSchedulingElbPort = CaeCommon::StrToUInt32(KEY_REMOTE_SCHEDULING_ELB_PORT.c_str(),
                                                       remoteSchedulingElbPort,
                                                       0);
}

void CaeMediaConfig::SetRepeatFps(const char *repeatFps) {
    m_repeatFps = CaeCommon::StrToUInt32(KEY_REPEAT_FPS.c_str(),
                                         repeatFps,
                                         0);
}

uint32_t CaeMediaConfig::GetRepeatFps() {
    return m_repeatFps;
}

uint32_t CaeMediaConfig::GetAudioType()
{
    return m_audioType;
}

void CaeMediaConfig::SetAudioType(const char* audioType) {
    m_audioType = CaeCommon::StrToUInt32(AV_AUDIO_TYPE,
                                         audioType,
                                         AUDIO_TYPE_PCM);
}

uint32_t CaeMediaConfig::GetSampleRate()  {
    return m_sampleRate;
}

void CaeMediaConfig::SetSampleRate(const char* sampleRate)
{
    m_sampleRate = CaeCommon::StrToUInt32(AV_SAMPLE_RATE,
                                          sampleRate,
                                          48000);
}

uint32_t CaeMediaConfig::GetChannels()
{
    return m_channels;
}

void CaeMediaConfig::SetChannels(const char* channels)
{
    m_channels = CaeCommon::StrToUInt32(AV_CHANNELS,
                                        channels,
                                        2);
}

uint32_t CaeMediaConfig::GetOpusInterval()
{
    return m_opusInterval;
}

void CaeMediaConfig::SetOpusInterval(const char* opusInterval)
{
    m_opusInterval = CaeCommon::StrToUInt32(AV_INTERVAL,
                                            opusInterval,
                                            2);
}

uint32_t CaeMediaConfig::GetOpusBitrate()
{
    return m_opusBitrate;
}

void CaeMediaConfig::SetOpusBitrate(const char* opusBitrate)
{
    m_opusBitrate = CaeCommon::StrToUInt32(AV_BITRATE,
                                           opusBitrate,
                                           2 * m_channels * m_sampleRate);
}

char* CaeMediaConfig::BuildDynamicVideoJsonConfig()
{
    char* jsonConfigStr;
    cJSON *jsonConfig = cJSON_CreateObject();

    if (jsonConfig == nullptr) {
        LOGW("cJson failed to create config json");
        return nullptr;
    }

    cJSON *bitrate = cJSON_CreateNumber(CaeConfigManage::IsOverrideBitrate() ? CaeConfigManage::GetOverrideBitrate() : m_bitrate);
    if (bitrate == nullptr) {
        LOGW("cJson failed to create bitrate json");
        cJSON_Delete(jsonConfig);
        return nullptr;
    } else {
        cJSON_AddItemToObject(jsonConfig, AV_BITRATE, bitrate);
    }

    m_streamWidth =
            m_streamWidth > 0 && m_streamWidth <= m_virtualWidthAlign ? m_streamWidth : m_virtualWidthAlign;
    m_streamHeight =
            m_streamHeight > 0 && m_streamHeight <= m_virtualHeightAlign ? m_streamHeight : m_virtualHeightAlign;

    cJSON *virtualWidth = cJSON_CreateNumber(m_streamWidth);
    if (virtualWidth == nullptr) {
        LOGW("cJson failed to create virtual width json");
        cJSON_Delete(jsonConfig);
        return nullptr;
    } else {
        cJSON_AddItemToObject(jsonConfig, AV_STREAM_WIDTH, virtualWidth);
    }

    cJSON *virtualHeight = cJSON_CreateNumber(m_streamHeight);
    if (virtualHeight == nullptr) {
        LOGW("cJson failed to create virtual height json");
        cJSON_Delete(jsonConfig);
        return nullptr;
    } else {
        cJSON_AddItemToObject(jsonConfig, AV_STREAM_HEIGHT, virtualHeight);
    }

    m_fps = CaeConfigManage::IsOverrideFPS() ? CaeConfigManage::GetOverrideFPS() : m_fps;
    cJSON *fps = cJSON_CreateNumber(m_fps);
    if (fps == nullptr) {
        LOGW("cJson failed to create frame rate json");
        cJSON_Delete(jsonConfig);
        return nullptr;
    } else {
        cJSON_AddItemToObject(jsonConfig, AV_FPS, fps);
    }

    cJSON *gopSize = cJSON_CreateNumber(m_gopSize);
    if (gopSize == nullptr) {
        LOGW("cJson failed to create gop size json");
        cJSON_Delete(jsonConfig);
        return nullptr;
    } else {
        cJSON_AddItemToObject(jsonConfig, AV_GOP_SIZE, gopSize);
    }

    cJSON *profile = cJSON_CreateNumber(m_profile);
    if (profile == nullptr) {
        LOGW("cJson failed to create profile json");
        cJSON_Delete(jsonConfig);
        return nullptr;
    } else {
        cJSON_AddItemToObject(jsonConfig, AV_PROFILE_TYPE, profile);
    }

    cJSON *rcMode = cJSON_CreateNumber(m_rcMode);
    if (rcMode == nullptr) {
        LOGW("cJson failed to create profile json");
        cJSON_Delete(jsonConfig);
        return nullptr;
    } else {
        cJSON_AddItemToObject(jsonConfig, AV_RC_MODE, rcMode);
    }

    m_repeatFps = std::min(m_fps, m_repeatFps);
    cJSON *repeatFps = cJSON_CreateNumber(m_repeatFps);
    if (repeatFps == nullptr) {
        LOGW("cJson failed to create repeat Fps json");
        cJSON_Delete(jsonConfig);
        return nullptr;
    } else {
        cJSON_AddItemToObject(jsonConfig, KEY_REPEAT_FPS.c_str(), repeatFps);
    }

    jsonConfigStr = cJSON_PrintUnformatted(jsonConfig);
    cJSON_Delete(jsonConfig);

    LOGI("json config is %s", jsonConfigStr);
    return jsonConfigStr;
}

char* CaeMediaConfig::BuildVideoJsonConfig()
{
    char* jsonConfigStr;
    cJSON *jsonConfig = cJSON_CreateObject();

    if (jsonConfig == nullptr) {
        LOGW("cJson failed to create config json");
        return nullptr;
    }

    cJSON *bitrate = cJSON_CreateNumber(CaeConfigManage::IsOverrideBitrate() ? CaeConfigManage::GetOverrideBitrate() : m_bitrate);
    if (bitrate == nullptr) {
        LOGW("cJson failed to create bitrate json");
        cJSON_Delete(jsonConfig);
        return nullptr;
    } else {
        cJSON_AddItemToObject(jsonConfig, AV_BITRATE, bitrate);
    }

    m_streamWidth =
            m_streamWidth > 0 && m_streamWidth <= m_virtualWidthAlign ? m_streamWidth : m_virtualWidthAlign;
    m_streamHeight =
            m_streamHeight > 0 && m_streamHeight <= m_virtualHeightAlign ? m_streamHeight : m_virtualHeightAlign;

    cJSON *streamWidth = cJSON_CreateNumber(m_streamWidth);
    if (streamWidth == nullptr) {
        LOGW("cJson failed to create virtual width json");
        cJSON_Delete(jsonConfig);
        return nullptr;
    } else {
        cJSON_AddItemToObject(jsonConfig, AV_STREAM_WIDTH, streamWidth);
    }

    cJSON *streamHeight = cJSON_CreateNumber(m_streamHeight);
    if (streamHeight == nullptr) {
        LOGW("cJson failed to create virtual height json");
        cJSON_Delete(jsonConfig);
        return nullptr;
    } else {
        cJSON_AddItemToObject(jsonConfig, AV_STREAM_HEIGHT, streamHeight);
    }

    m_fps = CaeConfigManage::IsOverrideFPS() ? CaeConfigManage::GetOverrideFPS() : m_fps;
    cJSON *fps = cJSON_CreateNumber(m_fps);
    if (fps == nullptr) {
        LOGW("cJson failed to create frame rate json");
        cJSON_Delete(jsonConfig);
        return nullptr;
    } else {
        cJSON_AddItemToObject(jsonConfig, AV_FPS, fps);
    }

    cJSON *frameType = cJSON_CreateString(m_videoFrameType.c_str());
    if (frameType == nullptr) {
        LOGW("cJson failed to create frame type json");
        cJSON_Delete(jsonConfig);
        return nullptr;
    } else {
        cJSON_AddItemToObject(jsonConfig, AV_VIDEO_FRAME_TYPE, frameType);
    }

    cJSON *gopSize = cJSON_CreateNumber(m_gopSize);
    if (gopSize == nullptr) {
        LOGW("cJson failed to create gop size json");
        cJSON_Delete(jsonConfig);
        return nullptr;
    } else {
        cJSON_AddItemToObject(jsonConfig, AV_GOP_SIZE, gopSize);
    }

    cJSON *profile = cJSON_CreateNumber(m_profile);
    if (profile == nullptr) {
        LOGW("cJson failed to create profile json");
        cJSON_Delete(jsonConfig);
        return nullptr;
    } else {
        cJSON_AddItemToObject(jsonConfig, AV_PROFILE_TYPE, profile);
    }

    cJSON *encodeType = cJSON_CreateNumber(m_encodeType);
    if (encodeType == nullptr) {
        LOGW("cJson failed to create encode type json");
        cJSON_Delete(jsonConfig);
        return nullptr;
    } else {
        cJSON_AddItemToObject(jsonConfig, KEY_ENCODE_TYPE.c_str(), encodeType);
    }

    cJSON *rcMode = cJSON_CreateNumber(m_rcMode);
    if (rcMode == nullptr) {
        LOGW("cJson failed to create profile json");
        cJSON_Delete(jsonConfig);
        return nullptr;
    } else {
        cJSON_AddItemToObject(jsonConfig, AV_RC_MODE, rcMode);
    }

    m_repeatFps = std::min(m_fps, m_repeatFps);
    cJSON *repeatFps = cJSON_CreateNumber(m_repeatFps);
    if (repeatFps == nullptr) {
        LOGW("cJson failed to create repeat Fps json");
        cJSON_Delete(jsonConfig);
        return nullptr;
    } else {
        cJSON_AddItemToObject(jsonConfig, KEY_REPEAT_FPS.c_str(), repeatFps);
    }

    if (!m_remoteSchedulingElbIp.empty()){
        cJSON *remoteSchedulingElbIp = cJSON_CreateString(m_remoteSchedulingElbIp.c_str());
        if (remoteSchedulingElbIp == nullptr) {
            LOGW("cJson failed to create remote scheduling elb ip json");
            cJSON_Delete(jsonConfig);
            return nullptr;
        } else {
            cJSON_AddItemToObject(jsonConfig, KEY_REMOTE_SCHEDULING_ELB_IP.c_str(), remoteSchedulingElbIp);
        }
    }

    if (!m_remoteSchedulingElbIp.empty() && m_remoteSchedulingElbPort != 0){
        cJSON *remoteSchedulingElbPort = cJSON_CreateNumber(m_remoteSchedulingElbPort);
        if (remoteSchedulingElbPort == nullptr) {
            LOGW("cJson failed to create remote scheduling elb port json");
            cJSON_Delete(jsonConfig);
            return nullptr;
        } else {
            cJSON_AddItemToObject(jsonConfig, KEY_REMOTE_SCHEDULING_ELB_PORT.c_str(), remoteSchedulingElbPort);
        }
    }
    jsonConfigStr = cJSON_PrintUnformatted(jsonConfig);
    cJSON_Delete(jsonConfig);

    LOGI("video json config is %s", jsonConfigStr);
    return jsonConfigStr;
}

char* CaeMediaConfig::BuildAudioJsonConfig()
{

    char* jsonConfigStr;
    cJSON *jsonConfig = cJSON_CreateObject();

    if (jsonConfig == nullptr) {
        LOGW("cJson failed to create config json");
        return nullptr;
    }

    cJSON *audioType = cJSON_CreateNumber(m_audioType);
    if (audioType == nullptr) {
        LOGW("cJson failed to create audioType json");
        cJSON_Delete(jsonConfig);
        return nullptr;
    } else {
        cJSON_AddItemToObject(jsonConfig, AV_AUDIO_TYPE, audioType);
    }

    cJSON *sampleRate = cJSON_CreateNumber(m_sampleRate);
    if (sampleRate == nullptr) {
        LOGW("cJson failed to create sampleRate json");
        cJSON_Delete(jsonConfig);
        return nullptr;
    } else {
        cJSON_AddItemToObject(jsonConfig, AV_SAMPLE_RATE, sampleRate);
    }

    cJSON *channels = cJSON_CreateNumber(m_channels);
    if (channels == nullptr) {
        LOGW("cJson failed to create channels json");
        cJSON_Delete(jsonConfig);
        return nullptr;
    } else {
        cJSON_AddItemToObject(jsonConfig, AV_CHANNELS, channels);
    }

    if (m_audioType == AUDIO_TYPE_OPUS) {
        cJSON *interval = cJSON_CreateNumber(m_opusInterval);
        if (interval == nullptr) {
            LOGW("cJson failed to create channels json");
            cJSON_Delete(jsonConfig);
            return nullptr;
        } else {
            cJSON_AddItemToObject(jsonConfig, AV_INTERVAL, interval);
        }

        cJSON *bitrate = cJSON_CreateNumber(m_opusBitrate);
        if (bitrate == nullptr) {
            LOGW("cJson failed to create bitrate json");
            cJSON_Delete(jsonConfig);
            return nullptr;
        } else {
            cJSON_AddItemToObject(jsonConfig, AV_BITRATE, bitrate);
        }
    }

    jsonConfigStr = cJSON_PrintUnformatted(jsonConfig);
    cJSON_Delete(jsonConfig);

    LOGI("audio json config is %s", jsonConfigStr);
    return jsonConfigStr;
}

char* CaeMediaConfig::BuildResponseVideoJsonConfig() {
    cJSON *jsonConfig = cJSON_CreateObject();

    if (jsonConfig == nullptr) {
        LOGW("cJson failed to create config json");
        return nullptr;
    }

    cJSON *frameType = cJSON_CreateString(m_videoFrameType.c_str());
    if (frameType == nullptr) {
        LOGW("cJson failed to create frame type json");
        cJSON_Delete(jsonConfig);
        return nullptr;
    } else {
        cJSON_AddItemToObject(jsonConfig, AV_VIDEO_FRAME_TYPE, frameType);
    }

    cJSON *width = cJSON_CreateNumber(CaeConfigManage::GetHardwareWidth());
    if (width == nullptr) {
        LOGW("cJson failed to create sampleRate json");
        cJSON_Delete(jsonConfig);
        return nullptr;
    } else {
        cJSON_AddItemToObject(jsonConfig, AV_PHYSICAL_WIDTH, width);
    }

    char* jsonConfigStr = cJSON_PrintUnformatted(jsonConfig);
    cJSON_Delete(jsonConfig);

    LOGI("response video json config is %s", jsonConfigStr);
    return jsonConfigStr;
}

bool CaeMediaConfig::IsNeedSetPhysicalResolution() const {
    return m_needSetPhysicalResolution;
}

void CaeMediaConfig::SetNeedSetPhysicalResolution(bool needSetPhysicalResolution) {
    CaeMediaConfig::m_needSetPhysicalResolution = needSetPhysicalResolution;
}

bool CaeMediaConfig::IsMute() const {
    return m_isMute;
}

void CaeMediaConfig::SetMute(const char* isMute) {
    m_isMute = CaeCommon::StrToUInt32(AV_MUTE, isMute, 1);
}

bool CaeMediaConfig::IsAutoQuality() const {
    return m_autoQuality;
}

void CaeMediaConfig::SetAutoQuality(const char* autoQuality) {
    m_autoQuality = CaeCommon::StrToUInt32(KEY_AUTO_QUALITY.c_str(), autoQuality, 1);
}

void CaeMediaConfig::SetQuality(const char* quality) {

    int beginIndex = m_videoFrameType == VIDEO_FRAME_TYPE_H265 ? 0 : 1;
    uint32_t bitrate = 0;
    if (std::strcmp(quality, QUALITY_BASIC) == 0) {
        bitrate = QUALITY[beginIndex];
    } else if (std::strcmp(quality, QUALITY_MAIN) == 0) {
        bitrate = QUALITY[beginIndex + 1];
    } else if (std::strcmp(quality, QUALITY_BEST) == 0) {
        bitrate = QUALITY[beginIndex + 2];
    } else {
        bitrate = m_bitrate;
    }

    if (CaeConfigManage::GetHardwareWidth() == SPEC_1080P_WIDTH) {
        bitrate = 2 * bitrate;
    }

    if (m_fps == 60) {
        bitrate = 2 * bitrate;
    }

    m_bitrate = bitrate;
    m_cmdBitrate = m_bitrate;
}

bool CaeMediaConfig::IsRemoteEncoderInfoValid()
{
    if (GetRemoteSchedulingElbIp().empty() || GetRemoteSchedulingElbPort() == 0) {
        return false;
    }
    return true;
}